package com.gin.kotlin.no_gay_alliance.provider.ngaphp

import android.util.Log
import com.gin.kotlin.no_gay_alliance.app.App
import com.gin.kotlin.no_gay_alliance.argument.ReplyListArgument
import com.gin.kotlin.no_gay_alliance.argument.ReplyListArgument.Type
import com.gin.kotlin.no_gay_alliance.database.entity.ReplyHistory
import com.gin.nga.main.NgaApi
import com.gin.nga.response.base.NgaResponse
import com.gin.nga.response.reply.ReplyListBody
import retrofit2.Call
import java.lang.ref.WeakReference
import java.util.Locale
import java.util.concurrent.TimeUnit
import kotlin.math.max

class ReplyListProvider private constructor() : AbstractCachedDataProvider<ReplyListArgument, ReplyListBody, ReplyListBody>(
    TYPE_FACTORY.constructType(ReplyListBody::class.java),
    TimeUnit.MINUTES.toSeconds(2)
) {
    override val dir = "REPLY_LIST"

    override fun transform(rawData: ReplyListBody) = rawData

    override fun requestMethod(ngaApi: NgaApi, params: ReplyListArgument?): Call<NgaResponse<ReplyListBody>> {
        val p = params ?: throw RuntimeException("必须提供参数")
        val api = ngaApi.topicReadApi

        return when (p.type) {
            Type.LIST -> if (!p.html) api.readTopic(p.topicId!!, p.page, p.userId) else api.readTopicHtml(p.topicId!!, p.page, p.userId)
            Type.SINGLE -> if (!p.html) api.readReply(p.replyId!!) else api.readReplyHtml(p.replyId!!)
            Type.HISTORY -> if (!p.html) api.readHistory(p.backupId!!, p.topicId!!, p.replyId) else api.readHistoryHtml(p.backupId!!, p.topicId!!, p.replyId)
        }
    }

    override fun onSuccess(data: NgaResponse<ReplyListBody>?) {
        val replies = data?.data?.replies ?: return
        val topicTitle = data.data?.topic?.title ?: return
        // 观察的用户和主题
        val observedUserId = App.INSTANCE.database.replyHistoryUserDao().list()?.map { it.userId }
        val observedTopicId = App.INSTANCE.database.replyHistoryTopicDao().list()?.map { it.topicId }
        val replyHistories = replies
            .flatMap { r ->
                val h = r.hotReplies?.toTypedArray() ?: arrayOf()
                val c = r.comment?.toTypedArray() ?: arrayOf()
                mutableListOf(r, *c, *h)
            }
            .filter { it.topicId != null && !it.content.isNullOrEmpty() }
            .map { ReplyHistory(it).also { r -> r.topicTitle = topicTitle } }
            .filter { observedUserId?.contains(it.authorUid) == true || observedTopicId?.contains(it.topicId) == true }
        // 需要保存的记录非空
        if (replyHistories.isNotEmpty()) {
            val dao = App.INSTANCE.database.replyHistoryDao()
            // 查询已有记录，替换楼层号
            val histories = dao.list(replyHistories.map { it.uuid }.toTypedArray())
            replyHistories.forEach { his -> histories?.firstOrNull { his.uuid == it.uuid }?.also { his.floorNumber = max(his.floorNumber, it.floorNumber) } }
            dao.add(replyHistories)
            Log.d(TAG, "记录 ${replyHistories.size} 条回复历史")
        }
    }

    override fun obtainRelativePath(userId: Long, params: ReplyListArgument?): String {
        val p = params ?: throw RuntimeException("必须提供参数")

        val name = when (p.type) {
            Type.LIST -> String.format(Locale.CHINESE, "%d_%d_%d", p.topicId!!, p.page, p.userId)
            Type.SINGLE -> String.format(Locale.CHINESE, "%d", p.replyId!!)
            Type.HISTORY -> String.format(Locale.CHINESE, "%d_%d_%d", p.backupId, p.topicId, p.replyId)
        }
        val dir = if (p.html) "html" else "json"

        return "$dir/${p.type.name}/$name.json"
    }

    companion object {
        private var instance: WeakReference<ReplyListProvider> = WeakReference(ReplyListProvider())
        fun getInstance(): ReplyListProvider = instance.get() ?: ReplyListProvider().also { instance = WeakReference(it) }
    }
}